package com.pivotal.cloud.security.jwt;

import com.pivotal.cloud.crypto.codec.Codecs;
import com.pivotal.cloud.crypto.sign.SignatureVerifier;
import com.pivotal.cloud.crypto.sign.Signer;

import java.nio.CharBuffer;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @className: com.pivotal.cloud.security.jwt.JwtHelper
 * @projectName: PivotalCloud项目
 * @module: PivotalCloud项目-JwtHelper类，主要位于Security安全模块-Jwt工具类模块
 * @content: JwtHelper-Jwt工具类
 * @author: Powered by Marklin
 * @datetime: 2025-06-21 20:39
 * @version: 1.0.0
 * @copyright: Copyright © 2018-2025 PivotalCloud Systems Incorporated. All rights
 * reserved.
 */
public class JwtHelper {

	static byte[] PERIOD = Codecs.utf8Encode(".");

	public JwtHelper() {
	}

	public static Jwt decode(String token) {
		int firstPeriod = token.indexOf(46);
		int lastPeriod = token.lastIndexOf(46);
		if (firstPeriod > 0 && lastPeriod > firstPeriod) {
			CharBuffer buffer = CharBuffer.wrap(token, 0, firstPeriod);
			JwtHeader header = JwtHeaderHelper.create(buffer.toString());
			buffer.limit(lastPeriod).position(firstPeriod + 1);
			byte[] claims = Codecs.b64UrlDecode(buffer);
			boolean emptyCrypto = lastPeriod == token.length() - 1;
			byte[] crypto;
			if (emptyCrypto) {
				if (!"none".equals(header.parameters.alg)) {
					throw new IllegalArgumentException("Signed or encrypted token must have non-empty crypto segment");
				}

				crypto = new byte[0];
			}
			else {
				buffer.limit(token.length()).position(lastPeriod + 1);
				crypto = Codecs.b64UrlDecode(buffer);
			}

			return new JwtImpl(header, claims, crypto);
		}
		else {
			throw new IllegalArgumentException("JWT must have 3 tokens");
		}
	}

	public static Jwt decodeAndVerify(String token, SignatureVerifier verifier) {
		Jwt jwt = decode(token);
		jwt.verifySignature(verifier);
		return jwt;
	}

	public static Map<String, String> headers(String token) {
		JwtImpl jwt = (JwtImpl) decode(token);
		Map<String, String> map = new LinkedHashMap(jwt.header.parameters.map);
		map.put("alg", jwt.header.parameters.alg);
		jwt.header.parameters.getClass();
		if ("JWT" != null) {
			jwt.header.parameters.getClass();
			map.put("typ", "JWT");
		}

		return map;
	}

	public static Jwt encode(CharSequence content, Signer signer) {
		return encode(content, signer, Collections.emptyMap());
	}

	public static Jwt encode(CharSequence content, Signer signer, Map<String, String> headers) {
		JwtHeader header = JwtHeaderHelper.create(signer, headers);
		byte[] claims = Codecs.utf8Encode(content);
		byte[] crypto = signer.sign(Codecs
				.concat(new byte[][] { Codecs.b64UrlEncode(header.bytes()), PERIOD, Codecs.b64UrlEncode(claims) }));
		return new JwtImpl(header, claims, crypto);
	}

}
